19-4 洏 Prototype.js 荈i AJAX ]p

目前在網路上最常被用到的 JavaScript framework,就是 prototype.js,可由下列網址下載:
http://www.prototypejs.org
所謂的 framework,可以看成是原先 JavaScript 的應用程式介面(API,或是 Appliation Program Interface),可以根基於基本的 JavaScript 來提供更先進的功能。我們本小節所用的 prototype.js 版本是 1.5.1.1(2007/06/19 發行),所提供的擴充功能如下: 在前一小節我們已經說明了 AJAX 的基本使用方式及範例,本小節將說明如何使用 prototype.js 來進行 AJAX 的網頁設計。首先,我們直接看看一個簡單的範例:

Example(ajax/ajaxViaPrototype01.htm):

這是一個查詢歌手的網頁,只要你在文字欄位輸入歌手名字,就可以使用 AJAX 的非同步傳輸方式,立即對資料庫 ajax/test.mdb 進行查詢,並將歌手資訊顯示在文字欄位下方。例如,當我們輸入「鄧麗君」並按下「送出」時,就會看到鄧麗君的資訊已經顯示在網頁下方:

Hint
這是一個比較老的資料庫,你也可以輸入其他歌手看看,例如周華健、巫啟賢、林憶蓮、莫文蔚、陶晶瑩等。

而這整個過程並沒有經由網頁的重載來達成。此範例的原始碼如下:

原始檔(ajax/ajaxViaPrototype01.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
</head>

<body>
<h2 align=center>AJAX Webpage Design Using Prototype.js</h2>
<hr>

<script src="prototype.js"></script>
<script>
// 顯示查詢結果
function showQueryResult(xmlHttpObj){
	Element.update('queryResult', xmlHttpObj.responseText);
}
// 送出對資料庫的查詢
function sendQuery() {
	var url = 'queryDb01.asp';				// 伺服器的程式網頁	
	var queryString = 'singerName=' + $F('singerName');	// 參數列
	var ajax = new Ajax.Request(url, {method:'post', parameters:queryString, onComplete:showQueryResult});
}
</script>

歌手大名:<input type="text" id="singerName" value="鄧麗君">
<input type="button" onClick="sendQuery()" value="送出">
<div id="queryResult"></div>

</body>
</html>

基本上,Prototype.js 只是將 XMLHttpRequest 「包起來」,基本的流程還是沒有變,以上一節所說的三個基本步驟來看,對應檔案及說明如下:

  1. 近端的發送函數:sendQuery()
    此函數定義了遠端的程式碼網頁(此例為 queryDb01.asp),同時也加入了參數列(此例為 singerName=鄧麗君),最後產生 AJAX 物件並定義相關參數,送到遠端執行。其中有幾點要注意:
    • 「$F('singerName')」是 Prototype.js 所提供的簡化語法,其功能全等於「document.getElementById('singerName').value」。同樣地,我們也可以使用「$('singerName')」來代表 id 為 singerName 的物件,其功能全等於「document.getElementById('singerName')」。

      Hint
      如果我們在 $() 之內輸入多個 id,此函數會回傳對應這些 id 的物件所成的陣列。

    • 產生 AJAX 物件的第二個參數是「{method:'post', parameters:queryString, onComplete:showQueryResult}」,此參數全等於一個具有三個欄位的物件,因此我們甚至可以將 sendQuery() 函數的第三列敘述: var ajax = new Ajax.Request(url, {method:'post', parameters:queryString, onComplete:showQueryResult}); 改成下列程式碼: var ajaxParam = new Object(); ajaxParam.method='post'; ajaxParam.parameters=queryString; ajaxParam.onComplete=showQueryResult; var ajax = new Ajax.Request(url, ajaxParam); 所得到的結果是一樣的。
  2. 遠端的程式碼:queryDb01.asp
    此程式碼如下:

    原始檔(ajax/queryDb01.asp):(灰色區域按兩下即可拷貝)
    <%@language=jscript%>
    <%//AJAX remot program in charge of database query%>
    <%Response.Charset="utf-8"%>
    <%
    // 傳回查詢資料庫的第一筆資料
    function getFirstRecordFromQueryResult(database, sql){
    	var Conn = Server.CreateObject("ADODB.Connection");
    	Conn.ConnectionString = "DBQ=" + Server.MapPath(database) + ";Driver={Microsoft Access Driver (*.mdb)};Driverld=25;FIL=MS Access;";
    	Conn.Open();
    	var RS = Conn.Execute(sql);
    	var out="<p><b>Query Result of <u>"+sql+"</u>:</b><p>";
    	if (RS.EOF)
    		return(out+"No data found!");
    	for (i=0; i<RS.Fields.Count; i++)
    		out=out+"<font color=red>"+RS(i).Name+"</font>: <font color=blue>"+RS(i)+"</font><br>";
    	RS.Close();
    	Conn.Close();
    	return(out);
    }
    
    database="test.mdb";		// 資料庫名稱
    sql="SELECT * from Singer where ChineseName = '"+Request("singerName")+"'";	// 造出 SQL 指令
    outStr=getFirstRecordFromQueryResult(database, sql);				// 回傳第一筆查詢結果
    Response.write(outStr);		// 印出查詢結果
    %>

    其功能很簡單,即是接收使用者輸入的歌手名字,造出 SQL 命令,並送入資料庫查詢,並將查詢結果印出來。

  3. 近端的接收函數:showQueryResult()
    在此函數中,我們只使用一列程式碼: Element.update('queryResult', xmlHttpObj.responseText); 這也是 Prototype.js 所提供的簡化語法,其功能全等於 document.getElementById('queryResult').innerHTML=xmlHttpObj.responseText
另外還有一點要特別注意:由於資料庫和網頁編碼的不一致,常會導致亂碼的產生,因此我們這個範例的兩個檔案(ajaxViaPrototype01.htm 和queryDb01.asp),都是採用 UTF-8 的編碼,因此讀者在開啟這些檔案時,要注意你的文字編輯器是否有支援 UTF-8 編碼的檔案編輯功能。

Hint
一般常用的文字編輯器,例如記事本(notepad.exe)及 UltraEdit,都支援 UTF-8 文字檔的檢視和編輯。

事實上,上述的範例還可以更簡單,如果我們只是將查詢結果顯示在網頁上,可以改用另一個 Prototype.js 對於 AJAX 所提供的函數 Ajax.Updater(),使用範例如下:

Example(ajax/ajaxViaPrototype02.htm):

此範例和前一個範例的功能完全相同,甚至連遠端的程式碼都是放在 queryDb01.asp,唯一不同的是,我們改用了 Ajax.Updater(),所以可以直接指定回傳資料所必須呈現的位置,範例原始碼如下:

原始檔(ajax/ajaxViaPrototype02.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
</head>

<body>
<h2 align=center>AJAX Webpage Design Using Updater() in Prototype.js</h2>
<hr>

<script src="prototype.js"></script>
<script>
// 送出對資料庫的查詢
function sendQuery() {
	var url = 'queryDb01.asp';				// 伺服器的程式網頁	
	var queryString = 'singerName=' + $F('singerName');	// 參數列
	var ajax = new Ajax.Updater('queryResult', url, {method:'post', parameters:queryString});
}
</script>

歌手大名:<input type="text" id="singerName" value="鄧麗君">
<input type="button" onClick="sendQuery()" value="送出">
<div id="queryResult"></div>

</body>
</html>

在上述原始碼中,Ajax.Updater() 的第一個參數是 'queryResult',這就是代表回傳資料將會被指定到 document.getElementById('queryResult').innerHTML,因此我們就不必另外在寫一個負責顯示結果的函數,換句話說,和前一個範例比較,我們已經不需要 showQueryResult() 這個函數了,所以整個網頁原始碼看起來更加簡潔。

若要對 AJAX 流程進行進一步的控制,我們可以使用 Ajax.Responders.register 來註冊幾個函數,以便顯示 AJAX 的工作流程。例如,在查詢資料庫時,若時間過久,我們通常希望能夠在網頁顯示「資料處理中...」等字樣,以免讓使用者以為是遠端伺服器當機了。以下這個簡單的範例,就能達到此功能:

Example(ajax/ajaxViaPrototype03.htm):

當我們點擊「送出」時,網頁會先顯示「資料處理中,請稍後...」等字樣,如下:

等查詢完畢後,所回傳的資料就會顯示在網頁上。此範例的原始碼如下:

原始檔(ajax/ajaxViaPrototype03.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
</head>

<body>
<h2 align=center>AJAX Webpage Design Using Responders.register in Prototype.js</h2>
<hr>

<script src="prototype.js"></script>
<script>
// 送出對資料庫的查詢
function sendQuery(){
	// 註冊 AJAX 某些事件所對應的函數
	Ajax.Responders.register ({
		onLoading:
			function(){
				Element.update('queryResult', '<font color=red>查詢資料中,請稍候...</font>');
			},
		onComplete:
			function(junk, xmlHttpObj){
				Element.update('queryResult', xmlHttpObj.responseText);
			}
		});
	var url = 'queryDb03.asp';				// 伺服器的程式網頁	
	var queryString = 'singerName=' + $F('singerName');	// 參數列
	var ajax = new Ajax.Request(url, {method:'post', parameters:queryString});
}
</script>

歌手大名:<input type="text" id="singerName" value="鄧麗君">
<input type="button" onClick="sendQuery()" value="送出">
<div id="queryResult"></div>

</body>
</html>

在此範例中,我們使用 Ajax.Responders.register() 來註冊了兩個函數,對應到 onLoading 事件的函數可以不斷印出「資料處理中,請稍後...」之訊息,而對應至 onComplete 事件的函數則可以顯示最後查詢結果。


JScript 程式設計與應用:用於伺服器端的 ASP 環境